import {
  Territory,
  Bucket,
  Common,
  Authorize,
  File, defaultConfig
} from "cess-js-sdk-frontend";
import { getAPI } from "../utils/init-polkadot-api";
import { formatBalance, formatBalanceStr } from "../utils/formatter";
import copy from "copy-to-clipboard";
import moment from "moment";
import store from "../utils/store";
import { notiOK, notiError } from "../utils/antd-helper";
import webconfig from "../webconfig";
import { message } from "antd";

let bucket = null,
  territory,
  authorizeHandle,
  fileHandle,
  common;

export {
  init,
  queryBlockHeight,
  getAccountsFromWallet,
  subState,
  signMessage,
  authSign,
  getAccount,
  getAddr,
  queryBalance,
  subscribeBalance,
  queryBucketList,
  createBucket,
  queryBucketInfo,
  deleteBucket,
  queryAuthorityList,
  checkAuthority,
  authorize,
  territories,//----------------territory
  territoryExtendTime,//----------------territory
  territoryExtendSize,//----------------territory
  territoryCreat,//----------------territory
  territoryRename,//----------------territory
  territoryReactivate,//----------------territory
  queryFileList,
  uploadFile,
  downloadFile,
  queryFileMetadata,
  deleteFile,
};

async function queryBlockHeight() {
  if (!bucket) {
    await init();
  }
  return await bucket.queryBlockHeight();
}
async function getAccountsFromWallet() {
  if (!bucket) {
    await init();
  }
  let accounts = await bucket.getAccountsFromWallet();
  return accounts;
}
async function init() {
  if (!bucket) {
    await getAPI();
    bucket = new Bucket(window.api, window.keyring, true);
    territory = new Territory(window.api, window.keyring, true);
    authorizeHandle = new Authorize(window.api, window.keyring, true);
    fileHandle = new File(
      window.api,
      window.keyring,
      webconfig.gatewayURL,
      true
    );
    common = new Common(window.api, window.keyring, true);
  }
  return {
    bucket,
    territory,
    authorizeHandle,
    fileHandle,
    common,
  };
}
function subState(ret) {
  try {
    // console.log("=============start=====================");
    // console.log(ret);
    // console.log("===============end===================");
    if (ret.status?.toJSON) {
      ret = ret.status.toJSON();
      let key = Object.keys(ret)[0];
      notiOK(key);
    }
  } catch (e) {
    console.log(e);
  }
}
async function signMessage(accountId, msg) {
  await init();
  if (typeof msg == 'string' && !msg.includes("<Bytes>")) {
    msg = `<Bytes>${msg}</Bytes>`;
  }
  let ret = await bucket.authSign(accountId, msg);
  console.log("authSign result", ret);
  let signStr = ret.signStr;
  if (!signStr) {
    return null;
  }
  return signStr.replace("0x", "");
}
async function authSign(accountId, msg) {
  await init();
  if (!msg.includes("<Bytes>")) {
    msg = `<Bytes>${msg}</Bytes>`;
  }
  let ret = await bucket.authSign(accountId, msg);
  return ret.bs58Str;
}

function getAccount() {
  let acc = store.get("account");
  return acc;
}
function getAddr() {
  let addr = store.get("addr");
  return addr;
}
async function queryBalance() {
  try {
    await init();
    let account = getAccount("account");
    if (!account || !account.address) return;
    console.log('queryBalance', account.address);
    const { nonce, data: balance } = await window.api.query.system.account(
      account.address
    );
    console.log("balance", balance);
    console.log(`balance of ${balance.free} and a nonce of ${nonce}`);
    account.nonce = nonce;
    account.balance = formatBalance(balance);
    account.balance_str = formatBalanceStr(balance.free.toString());
    store.set("account", account);
    return account;
  } catch (e) {
    console.log("query balance error");
    console.error(e);
  }
}
function subscribeBalance(cb) {
  let account = getAccount("account");
  if (!account || !account.address) return;
  common.subscribeBalance(account.address, (t) => {
    cb(t.free);
  });
}

//Bucket
async function queryBucketList() {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please(queryBucketList)");
  }
  let result = await bucket.queryBucketList(acc.address);
  return result;
}
async function createBucket(name) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please(createBucket)");
  }
  let result = await bucket.createBucket(acc.address, acc.address, name);
  return result;
}
async function queryBucketInfo(name) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please(queryBucketInfo)");
  }
  let result = await bucket.queryBucketInfo(acc.address, name);
  return result;
}
async function deleteBucket(name) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await bucket.deleteBucket(acc.address, acc.address, name);
  return result;
}

//Authority
async function queryAuthorityList() {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please(queryAuthorityList)");
  }
  let result = await authorizeHandle.authorityList(acc.address);
  return result;
}
async function checkAuthority() {
  let ret = await queryAuthorityList();
  console.log("checkAuthority", ret);
  return ret.data.includes(webconfig.gatewayAddr);
}
async function authorize() {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please(authorize)");
  }
  let result = await authorizeHandle.authorize(
    acc.address,
    webconfig.gatewayAddr,
    subState
  );
  return result;
}


//Space
async function territories() {
  await init();
  let acc = getAccount();
  if (!acc) {
    return { msg: "ok", data: [] }; // message.error("login firist please");
  }
  let result = await territory.queryMyTerritorys(acc.address);
  return result;
}
async function territoryCreat(territoryName, gibCount, days) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await territory.createTerritory(acc.address, territoryName, gibCount, days, subState);
  return result;
}
async function territoryExtendSize(territoryName, gibCount) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await territory.expandingTerritory(acc.address, territoryName, gibCount, subState);
  return result;
}
async function territoryExtendTime(territoryName, days) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await territory.renewalTerritory(acc.address, territoryName, days, subState);
  return result;
}
async function territoryReactivate(territoryName, days) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await territory.renewalTerritory(acc.address, territoryName, days, subState);
  return result;
}
async function territoryRename(oldName, newName) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await territory.renameTerritory(acc.address, oldName, newName, subState);
  return result;
}

//File
async function queryFileList() {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await fileHandle.queryFileListFull(acc.address);
  if (result.msg == "ok" && result.data && result.data.length > 0) {
    result.data.forEach((t) => {
      t.key = t.fileHash;
      t.keyIndex = t.key;
    });
  }
  let tmpList = store.get("tmpfiles");
  if (tmpList && tmpList.length > 0) {
    tmpList.forEach((tmp) => {
      let isExist = result.data.find((t) => t.fileHash == tmp.fileHash);
      if (!isExist) {
        result.data.push(tmp);
      }
    });
  }
  return result;
}
async function uploadFile(file, territoryName, progressCb, message = null, sign = null, evmacc, blockIndex) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await fileHandle.uploadFile(
    acc.address,
    file,
    territoryName,
    progressCb,
    message,
    sign,
    evmacc,
    evmacc,
    blockIndex
  );
  return result;
}
async function downloadFile(fileHash, savePath) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return; // message.error("login firist please");
  }
  let result = await fileHandle.downloadFile(fileHash, savePath);
  return result;
}
async function queryFileMetadata(fileHash) {
  await init();
  let result = await fileHandle.queryFileInfo(fileHash);
  return result;
}
async function deleteFile(fileHash, message = null, sign = null) {
  await init();
  let acc = getAccount();
  if (!acc) {
    return { msg: "login firist please" };
  }
  let result = await fileHandle.deleteFileByGateway(acc.address, fileHash, message, sign, acc.address, acc.evmAddress);
  return result;
}

window.getAccount = getAccount;
window.getAddr = getAddr;
